#include "e2d/ui/PrefebLoader.h"
#include "e2d/ui/Utils.h"
#include "e2d/core/Entity.h"
#include "e2d/core/impl/components.h"

std::unordered_map<std::string, std::shared_ptr<e2d::Entity>> e2d::PrefebLoader::m_PrefebEntities;

std::unordered_map<std::string, std::shared_ptr<e2d::Entity>> e2d::PrefebLoader::m_PrefebEntitiesNativeMap;

bool e2d::PrefebLoader::LoadFile(const fxcc::File& file)
{
    ztclog::info("Load prefeb %s", file.m_RelativePath.c_str());

    switch (file.m_FileType)
    {
    case fxcc::FileType::_Prefeb_:
        return LoadPrefebFile(file.m_RelativePath).get();
    default:
        return false;
    }
}

std::shared_ptr<e2d::Entity> e2d::PrefebLoader::LoadPrefebFromNativePath(const fxcc::File& file)
{
    PrefebImporter prefebImporter;
    bool flag = prefebImporter.ImportFileInc(file, true);
    ztclog::info("prefeb importer import file inc %d", flag);
    
    auto prefebPath = PrefebImporter::GetPrefebPathFromSource(file.m_RelativePath);
    auto prefebEntity = LoadPrefebFile(prefebPath);
    m_PrefebEntitiesNativeMap[file.m_RelativePath] = prefebEntity;
    return prefebEntity;
}

std::shared_ptr<e2d::Entity> e2d::PrefebLoader::LoadPrefebFile(const std::string& path)
{
    auto it = m_PrefebEntities.find(path);
    if (it != m_PrefebEntities.end())
    {
        return it->second;
    }

    auto prefebScene = e2d::Utils::m_Inst.m_PrefebScene;
    auto entity = prefebScene->NewEntity();

    fxcc::yml::Serializer serializer;
    bool flag = serializer.DecodePath<e2d::Entity>(path, *entity);

    if (flag)
    {
        m_PrefebEntities[path] = entity;
        return entity;
    }
   
    return 0;
}

std::shared_ptr<e2d::Entity> e2d::PrefebLoader::AddEntityToSceneNativePath(e2d::Scene* scene, e2d::Entity* parent,const std::string& nativePath)
{
    fxcc::File file(nativePath, false);

    auto prefebEntity = LoadPrefebFromNativePath(file);
    if (prefebEntity)
    {
        ztclog::info("add a gameobject from prefeb whose source is %s", file.m_RelativePath.c_str());

        std::shared_ptr<e2d::Entity> childEntity;
        
        if (parent)
        {
            childEntity = parent->NewChild();
        }
        else
        {
            childEntity = scene->NewEntity();
        }
        e2d::Components::CopyEntity(prefebEntity.get(), childEntity.get());

        childEntity->m_UUID = fxcc::Base::genUUID();
        return childEntity;
    }
    return 0;
}
